package cn.com.zzl.util;

import jxl.Cell;
import jxl.LabelCell;
import jxl.Sheet;
import jxl.Workbook;

import java.io.File;
import java.util.regex.Pattern;

/**
 * Description：jxl操作Excel2003表格之Sheet
 * 主要是工作表相关的操作，包括得到单元格、工作表的相关属性等
 * Created by 朱正磊 on 2017-04-27 16:33.
 */
public class SheetUtil {

	//Excel文件名（全路径名）
	private String fileName;

	//Excel中工作表的索引，从1开始
	private int index;

	public SheetUtil(){}

	/**
	 * @Desc 自定义构造函数
	 * @param fileName 文件名
	 * @param index 索引
	 */
	public SheetUtil(String fileName, int index) {
		this.fileName = fileName;
		this.index = index;
	}

	/**
	 * @Desc 获取工作表
	 * @return 返回工作表
	 * @throws Exception
	 */
	public Sheet getSheet() throws Exception {
		return Workbook.getWorkbook(new File(fileName)).getSheet(index-1);
	}

	/**
	 * @Desc 根据行列数获取指定的单元格
	 * @param column 列数，从1开始
	 * @param row 行数，从1开始
	 * @return 返回单元格
	 * @throws Exception
	 */
	public Cell getCell(int column, int row) throws Exception {
		return getSheet().getCell(column-1,row-1);
	}

	/**
	 * @Desc 根据行列数获取指定单元格的内容
	 * @param column 列数，从1开始
	 * @param row 行数，从1开始
	 * @return 返回单元格的内容
	 * @throws Exception
	 */
	public String getCellContents(int column, int row) throws Exception {
		return getCell(column,row).getContents();
	}

	/**
	 * @Desc 根据位置坐标获取单元格
	 * @param coordinate 位置坐标，比如A4，B2等等
	 * @return 返回单元格
	 * @throws Exception
	 */
	public Cell getCell(String coordinate) throws Exception {
		return getSheet().getCell(coordinate);
	}

	/**
	 * @Desc 根据位置坐标获取单元格的内容
	 * @param coordinate 位置坐标，比如A4，B2等等
	 * @return 返回单元格的内容
	 * @throws Exception
	 */
	public String getCellContents(String coordinate) throws Exception {
		return getCell(coordinate).getContents();
	}

	/**
	 * @Desc 获取工作表的行数
	 * @return 返回工作表的行数
	 * @throws Exception
	 */
	public int getRowLength() throws Exception {
		return getSheet().getRows();
	}

	/**
	 * @Desc 获取工作表的列数
	 * @return 返回工作表的列数
	 * @throws Exception
	 */
	public int getColumnLength() throws Exception {
		return getSheet().getColumns();
	}

	/**
	 * @Desc 根据行号获取该行单元格数组
	 * @param rowNum 行号从1开始
	 * @return
	 * @throws Exception
	 */
	public Cell[] getCellArrayOfRow(int rowNum) throws Exception {
		return getSheet().getRow(rowNum-1);
	}

	/**
	 * @Desc 根据列号获取该列单元格数组
	 * @param columnNum 列号从1开始
	 * @return
	 * @throws Exception
	 */
	public Cell[] getCellArrayOfColumn(int columnNum) throws Exception {
		return getSheet().getColumn(columnNum-1);
	}

	/**
	 * @Desc 获取工作表的名称
	 * @return 返回工作表的名称，比如第一个工作表的名称是sheetOne1
	 * @throws Exception
	 */
	public String getSheetName() throws Exception {
		return getSheet().getName();
	}

	/**
	 * @Desc 判断工作表是否是被隐藏的
	 * 这个方法不再建议使用。在新版本中有其他方法可以代替这个使用，以后的版本也不会再更新这个方法
	 * @return true：被隐藏； false：没有被隐藏
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	public boolean isHidden() throws Exception {
		return getSheet().isHidden();
	}

	/**
	 * @Desc 判断工作表是否是受保护的
	 * 这个方法不再建议使用。在新版本中有其他方法可以代替这个使用，以后的版本也不会再更新这个方法
	 * @return true：受保护； false：不受保护
	 * @throws Exception
	 */
	@SuppressWarnings("deprecation")
	public boolean isProtected() throws Exception {
		return getSheet().isProtected();
	}

	/**
	 * @Desc 得到内容与传进来字符串匹配的单元格，如果没有发现匹配，将返回null
			 搜索是从最低行开始一行一行执行的，因此，行号越低，算法执行越高效
	 * @param contents 匹配字符串
	 * @return 返回第一个匹配的单元格！！！
	 * @throws Exception
	 */
	public Cell findCellByContents(String contents) throws Exception {
		return getSheet().findCell(contents);
	}

	/**
	 * @Desc 根据内容查找内容为此的第一个单元格所在的行号（从1开始）
	 * @param contents 匹配字符串
	 * @return 返回第一个匹配的单元格所在的行号（从1开始），如果没找到则返回-1
	 * @throws Exception
	 */
	public int findRowNumOfCellByContents(String contents) throws Exception {
		if(findCellByContents(contents) == null) return -1;
		return findCellByContents(contents).getRow() + 1;
	}

	/**
	 * @Desc 得到内容与传进来字符串匹配的单元格，如果没有发现匹配，将返回null。
	         搜索是从最低行开始一行一行执行的，因此，行号越低，算法执行越高效。
			 Cell findCell(String contents,int firstCol,int firstRow,int lastCol,int lastRow,boolean reverse)
			 contents是匹配内容，firstCol是搜索开始列，firstRow是搜索开始行，同样lastCol，lastRow是搜索结束列和搜索结束行
			 reverse是指示是否执行反向搜索，反向搜索是从行、列数大的开始向小的方向搜索。true是执行反向搜索。
	 * @param contents 匹配内容
	 * @param firstColumn 搜索开始列（从1开始）
	 * @param firstRow 搜索开始行（从1开始）
	 * @param lastColumn 搜索结束列（从1开始）
	 * @param lastRow 搜索结束行（从1开始）
	 * @param reverse 是否执行反向搜索，true是执行反向搜索
	 * @return 返回第一个匹配单元格！！！
	 * @throws Exception
	 */
	public Cell findCellByCondition(String contents, int firstColumn, int firstRow,
									int lastColumn, int lastRow, boolean reverse) throws Exception {
		return getSheet().findCell(contents,firstColumn-1,firstRow-1,lastColumn-1,lastRow-1,reverse);
	}

	/**
	 * @Desc 根据条件查找匹配的第一个单元格所在的行号（从1开始）
	 * @param contents 匹配内容
	 * @param firstColumn 搜索开始列（从1开始）
	 * @param firstRow 搜索开始行（从1开始）
	 * @param lastColumn 搜索结束列（从1开始）
	 * @param lastRow 搜索结束行（从1开始）
	 * @param reverse 是否执行反向搜索，true是执行反向搜索
	 * @return 返回第一个匹配的单元格所在的行号（从1开始），如果没找到则返回-1
	 * @throws Exception
	 */
	public int findRowNumOfCellByCondition(String contents, int firstColumn, int firstRow,
										   int lastColumn, int lastRow, boolean reverse) throws Exception {
		if(findCellByCondition(contents,firstColumn,firstRow,lastColumn,lastRow,reverse) == null) return -1;
		return findCellByCondition(contents,firstColumn,firstRow,lastColumn,lastRow,reverse).getRow() + 1;
	}

	/**
	 * @Desc 得到内容与传进来字符串匹配的单元格，如果没有发现匹配，将返回null。
	 * @param pattern 正则表达式，比如Pattern pattern = Pattern.compile("^-?[0-9]+.?[0-9]*$");
	 * @param firstColumn 搜索开始列（从1开始）
	 * @param firstRow 搜索开始行（从1开始）
	 * @param lastColumn 搜索结束列（从1开始）
	 * @param lastRow 搜索结束行（从1开始）
	 * @param reverse 是否执行反向搜索，true是执行反向搜索
	 * @return 返回第一个匹配单元格！！！
	 * @throws Exception
	 */
	public Cell findCellByCondition(Pattern pattern, int firstColumn, int firstRow,
									int lastColumn, int lastRow, boolean reverse) throws Exception {
		return getSheet().findCell(pattern,firstColumn-1,firstRow-1,lastColumn-1,lastRow-1,reverse);
	}

	/**
	 * @Desc 根据条件查找匹配的第一个单元格所在的行号（从1开始）
	 * @param pattern 正则表达式，比如Pattern pattern = Pattern.compile("^-?[0-9]+.?[0-9]*$");
	 * @param firstColumn 搜索开始列（从1开始）
	 * @param firstRow 搜索开始行（从1开始）
	 * @param lastColumn 搜索结束列（从1开始）
	 * @param lastRow 搜索结束行（从1开始）
	 * @param reverse 是否执行反向搜索，true是执行反向搜索
	 * @return 返回第一个匹配的单元格所在的行号（从1开始），如果没找到则返回-1
	 * @throws Exception
	 */
	public int findRowNumOfCellByCondition(Pattern pattern, int firstColumn, int firstRow,
										   int lastColumn, int lastRow, boolean reverse) throws Exception {
		if(findCellByCondition(pattern,firstColumn,firstRow,lastColumn,lastRow,reverse) == null) return -1;
		return findCellByCondition(pattern,firstColumn,firstRow,lastColumn,lastRow,reverse).getRow() + 1;
	}

	/**
	 * @Desc 得到内容与传进来字符串匹配的单元格，如果没有发现匹配，将返回null
	 * 		 说明：只有标签单元格查询，所有的数值单元格被忽略，相比较findCell这应该能提高性能。
	 * @param contents 匹配字符串，只匹配字符串，不匹配数字。
	 * @return 返回第一个匹配的单元格！！！
	 * @throws Exception
	 */
	public LabelCell findLabelCellByContents(String contents) throws Exception {
		return getSheet().findLabelCell(contents);
	}

	/**
	 * @Desc 根据内容查找内容为此的第一个单元格所在的行号（从1开始）
	 * @param contents 匹配字符串，只匹配字符串，不匹配数字。
	 * @return 返回第一个匹配的单元格所在的行号（从1开始），如果没找到则返回-1
	 * @throws Exception
	 */
	public int findRowNumOfLabelCellByContents(String contents) throws Exception {
		if(findLabelCellByContents(contents) == null) return -1;
		return findLabelCellByContents(contents).getRow() + 1;
	}

	public String getFileName() {
		return fileName;
	}
	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public int getIndex() {
		return index;
	}
	public void setIndex(int index) {
		this.index = index;
	}
}
